﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace EnsureThat
{
	public static class Is
	{
		public static void NotNull<T>(T obj, string name)
			where T : class
		{
			if (obj == null)
				throw new ArgumentNullException(name);
		}
		public static void NotNull<T>(T? obj, string name)
			where T:struct
		{
			if(!obj.HasValue)
				throw new ArgumentNullException(name);
		}
	}
	public static class StringIs
	{
		public static void NotNullOrEmpty(string obj, string name)
		{
			if (string.IsNullOrEmpty(obj))
				throw new ArgumentException("String cannot be null or empty!", name);
		}
		public static void NotNullOrWhiteSpace(string obj, string name)
		{
			if (string.IsNullOrWhiteSpace(obj))
				throw new ArgumentException("String cannot be null or whitespace!", name);
		}
		public static Rule<string> Matches(string pattern)
		{
			return Matches(new Regex(pattern));
		}

		private static Rule<string> Matches(Regex regex)
		{
			return (o, n) =>
				{
					if (!regex.IsMatch(o))
						throw new ArgumentException("Must match pattern \"" + regex.ToString() + "\"", n);
				};
		}
	}
	public static class CollectionIs
	{
		public static void NotEmpty<T>(IEnumerable<T> obj, string name)
		{
			if (!obj.Any())
				throw new ArgumentException("Collection cannot be empty!", name);
		}
		public static Rule<IEnumerable<T>> HasAtLeast<T>(int numElements)
		{
			return (o, n) =>
				{
					int i = 0;
					foreach (var item in o)
						if(i++ >= numElements)
							return;
					throw new ArgumentException("Collection must consist of at least " + numElements.ToString() + " elements!", n);
				};
		}
	}
	public static class BoolIs
	{
		public static void IsTrue(bool obj, string name)
		{
			if (obj)
				throw new ArgumentException("Must be true!", name);
		}
		public static void IsFalse(bool obj, string name)
		{
			if (!obj)
				throw new ArgumentException("Must be true!", name);
		}
	}
}
